package com.example.micro.thread.future;

import org.springframework.scheduling.concurrent.CustomizableThreadFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;

public class AsyncThread {

    /**
     * 打印结果
     *
     * @param args
     */
    public static void main(String[] args) {
        AsyncThread asyncThread = new AsyncThread();
        List<String> resList = asyncThread.getResult(asyncThread.generate(10));
        resList.forEach(System.out::println);
    }

    /**
     * 遍历结果，整合至一个list中
     *
     * @param futureList
     * @return
     */
    private List<String> getResult(List<Future<String>> futureList) {
        List<String> resList = new ArrayList<>();
        for (Future<String> future : futureList) {
            try {
                while (true) {
                    if (future.isDone()) {
                        String res = future.get();
                        resList.add(res);
                        break;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return resList;
    }

    /**
     * 设置一个线程池，执行callable逻辑，通过future接收结果
     *
     * @param count
     * @return
     */
    public List<Future<String>> generate(int count) {
        int threadNum = Runtime.getRuntime().availableProcessors();
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                threadNum, threadNum, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<>(),
                new CustomizableThreadFactory("thread-pool-"));
        List<Future<String>> futureList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            Future<String> stringFuture = poolExecutor.submit(getJob(i));
            futureList.add(stringFuture);
        }
        poolExecutor.shutdown();
        return futureList;
    }

    /**
     * 定义任务执行逻辑
     *
     * @param i
     * @return
     */
    public Callable<String> getJob(final int i) {
        int time = new Random().nextInt(10);
        return () -> {
            Thread.sleep(1000 + time * i);
            return "thread-" + i;
        };
    }

}
